package com.ruoyi.framework.websocket;

import cn.hutool.json.JSON;
//import com.alibaba.fastjson2.JSON;
import cn.hutool.json.JSONUtil;
import com.ruoyi.framework.point.PointTable;
import com.ruoyi.framework.pojo.WebSocketPushInfo;
import com.ruoyi.framework.util.UserNameAndParams;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.Session;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * websocket 客户端用户集
 *
 * @author ruoyi
 */
@Slf4j
@Component
public class WebSocketUsers {

    @Autowired
    private PointTable pointTable;

    /**
     * 用户集
     */
    private static Map<String, Session> USERS = new ConcurrentHashMap<String, Session>();

    /**
     * deviceName,userNameParams
     */
    private static Map<String, List<UserNameAndParams>> deviceNameAndUserNameParams = new HashMap<>();

    /**
     * 存储用户
     *
     * @param key     唯一键
     * @param session 用户信息
     */
    public static void put(String key, Session session) {
        USERS.put(key, session);
    }

    /**
     * 移除用户
     *
     * @param session 用户信息
     * @return 移除结果
     */
    public static boolean remove(Session session) {
        String key = null;
        boolean flag = USERS.containsValue(session);
        if (flag) {
            Set<Map.Entry<String, Session>> entries = USERS.entrySet();
            for (Map.Entry<String, Session> entry : entries) {
                Session value = entry.getValue();
                if (value.equals(session)) {
                    key = entry.getKey();
                    break;
                }
            }
        } else {
            return true;
        }
        return remove(key);
    }

    /**
     * 移出用户
     *
     * @param key 键
     */
    public static boolean remove(String key) {
        log.info("\n 正在移出用户 - {}", key);
        Session remove = USERS.remove(key);
        if (remove != null) {
            boolean containsValue = USERS.containsValue(remove);
            log.info("\n 移出结果 - {}", containsValue ? "失败" : "成功");
            return containsValue;
        } else {
            return true;
        }
    }

    /**
     * 获取在线用户列表
     *
     * @return 返回用户集合
     */
    public static Map<String, Session> getUsers() {
        return USERS;
    }

//    /**
//     * 群发消息文本消息
//     *
//     * @param message 消息内容
//     */
//    public static void sendMessageToUsersByText(String message)
//    {
//        Collection<Session> values = USERS.values();
//        for (Session value : values)
//        {
//            sendMessageToUserByText(value, message);
//        }
//    }

    /**
     * 发送文本消息
     *
     * @param session 自己的用户名
     * @param message 消息内容
     */
    public static void sendMessageToUserByText(String tokenId, Session session, String message) {

        if (session == null) {
            session = USERS.get(tokenId);
        }
        if (null != session && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                log.error("\n[发送消息异常]", e);
            }
        } else {
            USERS.remove(tokenId);
            log.info("\n[你已离线]");
        }
    }

    public static void heartBeat() {

    }

    /**
     * 增加订阅点
     */

    public static void addSubscriptions(String username, String deviceName, String params, String value) {

        List<UserNameAndParams> userNameAndParams1 = deviceNameAndUserNameParams.get(deviceName);
        if (null == userNameAndParams1) {
            UserNameAndParams build = UserNameAndParams.builder().userName(username).params(params).value(value).build();
            List<UserNameAndParams> userNameAndParams = new ArrayList<>();
            userNameAndParams.add(build);
            deviceNameAndUserNameParams.put(deviceName, userNameAndParams);
        } else {
            UserNameAndParams build = UserNameAndParams.builder().userName(username).params(params).value(value).build();
            userNameAndParams1.add(build);
            deviceNameAndUserNameParams.put(deviceName, userNameAndParams1);
        }
    }

    public static void removeSubscriptions(String username, String deviceName, String params, String value) {
        List<UserNameAndParams> userNameAndParams = deviceNameAndUserNameParams.get(deviceName);
        if (null == userNameAndParams) {
            return;
        }
        for (UserNameAndParams userNameAndParam : userNameAndParams) {
            if (userNameAndParam.getParams().equals(params) && userNameAndParam.getUserName().equals(username)) {
                userNameAndParams.remove(userNameAndParam);
            }
        }
        deviceNameAndUserNameParams.put(deviceName, userNameAndParams);

    }

    public void pushInfo(String deviceName, String type) {
        if (USERS.isEmpty()) {
            return;
        }
        if (deviceNameAndUserNameParams.keySet().contains(deviceName)) {
            for (UserNameAndParams userNameAndParams : deviceNameAndUserNameParams.get(deviceName)) {
                String userName = userNameAndParams.getUserName();
                WebSocketPushInfo webSocketPushInfoBuilder = WebSocketPushInfo.builder().type(type)
                        .data(pointTable.read(deviceName, userNameAndParams.getParams(), userNameAndParams.getValue()))
                        .parameters(userNameAndParams.getParams())
                        .deviceName(deviceName).build();
                String jsonStr = JSONUtil.toJsonStr(webSocketPushInfoBuilder);
                sendMessageToUserByText(userName, USERS.get(userName), jsonStr);//pointTable read
            }
        }
    }

}
